package solver;

import java.util.ArrayList;
import java.util.List;

public class Utility {
	public static double sumToP(double[] in, int p) {
		double out = 0.0;
		for(int i = 0; i<=p; i++) {
			out += in[i];
		}
		return out;
	}

	
	public static double[] subArray(double[] in, int index1, int index2) {
		double[] out = new double[index2-index1];
		for(int i = 0; i<index2-index1; i++) {
			out[i] = in[i+index1];
		}
		return out;
	}
	
	public static List<List<int[]>> copyListListIntArray(List<List<int[]>> in) {
		List<List<int[]>> out = new ArrayList<List<int[]>>();
		for(int i = 0; i<in.size(); i++) {
			out.add(new ArrayList<int[]>());
			for (int j=0; j<in.get(i).size(); j++) {
				out.get(i).add(in.get(i).get(j));
			}
		}
		return out;
	}
	
	public static float[][] convertMatrixDoubleFloat(double[][] in) {
		float[][] out = new float[in.length][in.length];
		
		for (int i = 0; i<in.length; i++) {
			for (int j = 0; j<in.length; j++) {
				out[i][j] = (float)in[i][j];
			}
		}
		return out;                          
	}

	public static float[] convertArrayDoubleFloat(double[] in) {
		float[] out = new float[in.length];
		
		for (int i = 0; i<in.length; i++) {
				out[i] = (float)in[i];
		}
		return out;                          
	}

	
	public static double[][] copyMatrix(double[][] v1) {
		double[][] result = new double[v1.length][v1.length];
    	for (int i = 0; i<v1.length; i++) {
    		for (int j = 0; j<v1.length; j++) {
			result[i][j] = v1[i][j];
    		}
		}
    	return result;
	}

	
	public static double[] addVector(double[] v1, double[] v2) {
		double[] result = new double[v1.length];
    	for (int i = 0; i<v1.length; i++) {
			result[i] = v1[i]+v2[i];
		}
    	return result;
	}

	public static double[][] addMatrix(double[][] v1, double[][] v2) {
		double[][] result = new double[v1.length][v1.length];
    	for (int i = 0; i<v1.length; i++) {
    		for (int j = 0; j<v1.length; j++) {
			  result[i][j] = v1[i][j]+v2[i][j];
    		}
		}
    	return result;
	}
    public static double[] multVectorByConstant(double[] v1, double c) {
    	double[] result = new double[v1.length];
    	for (int i = 0; i<v1.length; i++) {
			result[i] = v1[i]*c;
		}
    	return result;
	}

	public static void printArray(int[] x) {
		System.out.print("[ ");
		for (int i = 0; i<x.length; i++) {
			System.out.print(x[i] + " ");
		}
		System.out.print("]");
	}

    
	public static void printArray(double[] x) {
		System.out.print("[ ");
		for (int i = 0; i<x.length; i++) {
			System.out.print(x[i] + " ");
		}
		System.out.println("]");
	}
	
	public static void printMatrix(double[][] x) {
		for (int i = 0; i<x.length; i++) {
			System.out.print("[ ");
			for (int j = 0; j<x.length; j++) {
			System.out.print(x[i][j] + " ");
			}
			System.out.println("]");
		}
	}
	
	
	public static double[][][] transposeMatrix(double[][][] x) {
		double[][][] result = new double[x.length][x.length][x.length];
		for(int i = 0; i<x.length; i++) {
			for(int j = 0; j<x.length; j++) {
				for(int k = 0; k<x.length; k++) {
				  result[i][j][k] = x[i][k][j];
				  //result[i][j][k] = x[k][j][i];
				}
			}	
		}
		return result;
	}

	
	public static double[][] divideMatrixConstant(double[][] jac, double x) {
		double[][] result = new double[jac.length][jac.length];
		for (int i = 0; i<jac.length; i++) {
			for (int j = 0; j<jac.length; j++) {
				result[i][j] = jac[i][j]/x;
			}	
		}
		return result;
	}
	
	
	public static double[][] multMatrixConstant(double[][] jac, double x) {
		double[][] result = new double[jac.length][jac.length];
		for (int i = 0; i<jac.length; i++) {
			for (int j = 0; j<jac.length; j++) {
				result[i][j] = jac[i][j]*x;
			}	
		}
		return result;
	}
	
	public static double[] multMatrixVector(double[][] jac, double[] x) {
		double[] result = new double[x.length];
		for (int i = 0; i<x.length; i++) {
			for (int j = 0; j<x.length; j++) {
				result[j] = result[j] + jac[j][i]*x[i];
			}	
		}
		return result;
	}
	
	public static double[][] multMatrixMatrix(double[][] a, double[][] b) {
		double[][] result = new double[a.length][a.length];
		double sum = 0.0;
		for (int j = 0; j<a.length; j++) {
		 for (int i = 0; i<a.length; i++) {
			 sum = 0;
			for (int k = 0; k<a.length; k++) {
				sum += a[i][k] * b[k][j];
			}	
			result[i][j] = sum;
		 }
		}
		return result;
	}

	
	
	public static double[] copyArray(double[] in) {
		double[] out = new double[in.length];
		for (int i = 0; i<out.length; i++){
			out[i] = in[i];
		}
		return out;
	}
	
	public static double[] reverseArray(double[] in) {
		double[] out = new double[in.length];
		for (int i = 0; i<out.length; i++){
			out[(out.length-1)-i] = in[i];
		}
		return out;
	}
	
	public static double[] cumsum(double[] in) {
		double[] out = new double[in.length];
		double sum = 0.0;
		for (int i = 0; i<out.length; i++){
			sum += in[i];
			out[i] = sum;
		}
		return out;
	}

	public static double[] subtractVectorScalar(double[] in, double s) {
		double[] out = new double[in.length];
		for (int i = 0; i<out.length; i++){
			out[i] = in[i]-s;
		}
		return out;	
	}
	
	public static double[] dividePairwiseVectorVector(double[] in1, double[] in2) {
		double[] out = new double[in1.length];
		for (int i = 0; i<out.length; i++){
			out[i] = in1[i]/in2[i];
		}
		return out;	
	}
	
	public static double[] makeCountVector(int num) {
		double[] out = new double[num];
		for (int i = 0; i< num; i++){
			out[i] = i+1;
		}
		return out;
	}

	public static double[][] repmatRow(double[] in) {
		double[][] out = new double[in.length][in.length];
		for (int i = 0; i< in.length; i++){
			for (int j = 0; j< in.length; j++){
				out[i][j] = in[j];
			}	
		}
		return out;
	}
	
	public static double[][] repmatCol(double[] in) {
		double[][] out = new double[in.length][in.length];
		for (int i = 0; i< in.length; i++){
			for (int j = 0; j< in.length; j++){
				out[i][j] = in[i];
			}	
		}
		return out;
	}
	
	public static double[][] subtractMatrix(double[][] in1, double[][] in2) {
		double[][] out = new double[in1.length][in1.length];
		for (int i = 0; i< in1.length; i++){
			for (int j = 0; j< in1.length; j++){
				out[i][j] = in1[i][j]-in2[i][j];
			}	
		}
		return out;
	}
	
	public static double[][] makeGreaterThanZero(double[][] in) {
		double[][] out = new double[in.length][in.length];
		for (int i = 0; i< in.length; i++){
			for (int j = 0; j< in.length; j++){
				out[i][j] = in[i][j];
				if (out[i][j] <= 0) {
					out[i][j] = 0;
				} else {
					out[i][j] = 1;
				}
			}	
		}
		return out;
	}
	
	public static double[] colsum(double[][] in) {
		double[] out = new double[in.length];
		for (int i = 0; i< in.length; i++){
			for (int j = 0; j< in.length; j++){
				out[j] += in[i][j];
			}	
		}
		return out;
	}
	
	public static double[] checkequals(double[] in1, double[] in2) {
		double[] out = new double[in1.length];
		for (int i = 0; i<in1.length; i++) {
			if (Math.abs(in1[i] - in2[i]) < 0.0000000000000001) {
				out[i] = 1; // true, equals
			} else {
				out[i] = 0; // false, not equals
			}
		}
		return out;
	}
	
	public static ArrayList<Integer> find(double[] in) {
		ArrayList<Integer> out = new ArrayList<Integer>();
		for (int i=0; i<in.length; i++) {
			if (Math.abs(in[i]) > 0.0000000000000001) {
				out.add(i);
			}
		}
		return out;
	}
	
	public static ArrayList<Double> getElements(double[] in, ArrayList<Integer> found) {
		ArrayList<Double> out = new ArrayList<Double>();
		for(int i = 0 ; i<found.size(); i++) {
			out.add(in[found.get(i)]);
		}
		return out;
	}
	
	public static double[] maxOrZero(double[] in) {
		double[] max = new double[in.length];
		for (int i = 0; i<in.length; i++) {
			if (in[i] > 0) {
				max[i] = in[i];
			} else {
				max[i] = 0.0;
			}
		}
		return max;
	}

}
